package com.phonetools.commonutils.android.content

import android.content.SharedPreferences
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty

private inline fun <T> SharedPreferences.delegate(
    key: String,
    defValue: T,
    crossinline getter: SharedPreferences.(String, T) -> T,
    crossinline setter: SharedPreferences.Editor.(String, T) -> SharedPreferences.Editor
): ReadWriteProperty<Any, T> = object : ReadWriteProperty<Any, T> {
    override fun getValue(thisRef: Any, property: KProperty<*>): T =
        getter(key, defValue) ?: defValue

    override fun setValue(thisRef: Any, property: KProperty<*>, value: T) =
        edit().setter(key, value).apply()

}

private inline fun <T> SharedPreferences.delegateNullable(
    key: String,
    defValue: T,
    crossinline getter: SharedPreferences.(String, T?) -> T?,
    crossinline setter: SharedPreferences.Editor.(String, T?) -> SharedPreferences.Editor
): ReadWriteProperty<Any, T> = object : ReadWriteProperty<Any, T> {
    override fun getValue(thisRef: Any, property: KProperty<*>): T =
        getter(key, defValue) ?: defValue

    override fun setValue(thisRef: Any, property: KProperty<*>, value: T) =
        edit().setter(key, value).apply()

}

/**
 * SharedPreferences Int 读写代理
 * @param  key 存储key
 * @param  defValue 默认值
 * @return 返回代理
 */
fun SharedPreferences.int(key: String, defValue: Int = 0): ReadWriteProperty<Any, Int> =
    delegate(key, defValue, SharedPreferences::getInt, SharedPreferences.Editor::putInt)

/**
 * SharedPreferences Long 读写代理
 * @param  key 存储key
 * @param  defValue 默认值
 * @return 返回代理
 */
fun SharedPreferences.long(key: String, defValue: Long = 0): ReadWriteProperty<Any, Long> =
    delegate(key, defValue, SharedPreferences::getLong, SharedPreferences.Editor::putLong)

/**
 * SharedPreferences Float 读写代理
 * @param  key 存储key
 * @param  defValue 默认值
 * @return 返回代理
 */
fun SharedPreferences.float(key: String, defValue: Float = 0f): ReadWriteProperty<Any, Float> =
    delegate(key, defValue, SharedPreferences::getFloat, SharedPreferences.Editor::putFloat)

/**
 * SharedPreferences Boolean 读写代理
 * @param  key 存储key
 * @param  defValue 默认值
 * @return 返回代理
 */
fun SharedPreferences.boolean(
    key: String,
    defValue: Boolean = false
): ReadWriteProperty<Any, Boolean> =
    delegate(key, defValue, SharedPreferences::getBoolean, SharedPreferences.Editor::putBoolean)

/**
 * SharedPreferences Set<String> 读写代理
 * @param  key 存储key
 * @param  defValue 默认值
 * @return 返回代理
 */
fun SharedPreferences.stringSet(
    key: String,
    defValue: Set<String> = emptySet()
): ReadWriteProperty<Any, Set<String>> =
    delegateNullable(
        key, defValue,
        SharedPreferences::getStringSet,
        SharedPreferences.Editor::putStringSet
    )

/**
 * SharedPreferences String 读写代理
 * @param  key 存储key
 * @param  defValue 默认值
 * @return 返回代理
 */
fun SharedPreferences.string(key: String, defValue: String = ""): ReadWriteProperty<Any, String> =
    delegateNullable(
        key,
        defValue,
        SharedPreferences::getString,
        SharedPreferences.Editor::putString
    )

/**
 * SharedPreferences Double 读写代理
 * @param  key 存储key
 * @param  defValue 默认值
 * @return 返回代理
 */
fun SharedPreferences.double(key: String, defValue: Double = 0.0) =
    object : ReadWriteProperty<Any, Double> {
        override fun getValue(thisRef: Any, property: KProperty<*>): Double {
            if (!contains(key)) {
                return defValue
            }
            val value = getLong(key, 0)
            return Double.fromBits(value)
        }

        override fun setValue(thisRef: Any, property: KProperty<*>, value: Double) =
            edit().putLong(key, value.toBits()).apply()

    }
